// -----------------------------
// Author: 		Dhaenens Gert 
// Creation: 	8/4/2013 9:59:38 PM				
// -----------------------------

#ifndef _LuaFunction_h
#define _LuaFunction_h

#include "LuaDataType.h"
#include "LuaObject.h"
#include "LuaRef.h"
#include "LuaStackGuard.h"
#include "Lua.h"
#include "LuaStack.h"

namespace ObjectLua
{

	namespace Internal
	{

		/*
		//	Used for binding
		//	a function to Lua
		//	0 Arguments
		//	Used internally
		*/
		template<typename R>
		class LuaFunction_0 : public LuaObject
		{
		public:
			typedef R (*Function)();
			typedef LuaFunction_0<R>	Type;

			LuaFunction_0(Lua* lpLua, Function lpFunction) : LuaObject(lpLua) , m_lpFunction(lpFunction) {}
			~LuaFunction_0() {}

			/*
			//	Used to actually bind
			//	the Function to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Function lpFunction);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Function
			*/
			int	call() const;

		private:
			Function	m_lpFunction;
		};



		/*
		//	Used for binding
		//	a function to Lua
		//	1 Argument
		//	Used internally
		*/
		template<typename R, typename P0>
		class LuaFunction_1 : public LuaObject
		{
		public:
			typedef R(*Function)(P0);
			typedef LuaFunction_1<R,P0>	Type;

			LuaFunction_1(Lua* lpLua, Function lpFunction) : LuaObject(lpLua) , m_lpFunction(lpFunction) {}
			~LuaFunction_1() {}

			/*
			//	Used to actually bind
			//	the Function to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Function lpFunction);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Function
			*/
			int	call() const;

		private:
			Function	m_lpFunction;
		};

		/*
		//	Used for binding
		//	a function to Lua
		//	2 Arguments
		//	Used internally
		*/
		template<typename R, typename P0, typename P1>
		class LuaFunction_2 : public LuaObject
		{
		public:
			typedef R (*Function)(P0,P1);
			typedef LuaFunction_2<R,P0,P1>	Type;


			LuaFunction_2(Lua* lpLua, Function lpFunction) : LuaObject(lpLua) , m_lpFunction(lpFunction) {}
			~LuaFunction_2() {}

			/*
			//	Used to actually bind
			//	the Function to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Function lpFunction);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Function
			*/
			int	call() const;

		private:
			Function	m_lpFunction;
		};



		/*
		//	Used for binding
		//	a function to Lua
		//	3 Arguments
		//	Used internally
		*/
		template<typename R, typename P0, typename P1, typename P2>
		class LuaFunction_3 : public LuaObject
		{
		public:
			typedef R(*Function)(P0, P1, P2);
			typedef LuaFunction_3<R,P0,P1,P2>	Type;

			LuaFunction_3(Lua* lpLua, Function lpFunction) : LuaObject(lpLua) , m_lpFunction(lpFunction) {}
			~LuaFunction_3() {}

			/*
			//	Used to actually bind
			//	the Function to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Function lpFunction);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Function
			*/
			int	call() const;

		private:
			Function	m_lpFunction;
		};



		/*
		//	Used for binding
		//	a function to Lua
		//	4 Arguments
		//	Used internally
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3>
		class LuaFunction_4 : public LuaObject
		{
		public:
			typedef R(*Function)(P0, P1, P2, P3);
			typedef LuaFunction_4<R,P0,P1,P2,P3>	Type;

			LuaFunction_4(Lua* lpLua, Function lpFunction) : LuaObject(lpLua) , m_lpFunction(lpFunction) {}
			~LuaFunction_4() {}

			/*
			//	Used to actually bind
			//	the Function to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Function lpFunction);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Function
			*/
			int	call() const;

		private:
			Function	m_lpFunction;
		};



		/*
		//	Used for binding
		//	a function to Lua
		//	5 Arguments
		//	Used internally
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3, typename P4>
		class LuaFunction_5 : public LuaObject
		{
		public:
			typedef R(*Function)(P0, P1, P2, P3, P4);
			typedef LuaFunction_5<R,P0,P1,P2,P3,P4>	Type;

			LuaFunction_5(Lua* lpLua, Function lpFunction) : LuaObject(lpLua) , m_lpFunction(lpFunction) {}
			~LuaFunction_5() {}

			/*
			//	Used to actually bind
			//	the Function to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Function lpFunction);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Function
			*/
			int	call() const;

		private:
			Function	m_lpFunction;
		};



		/*
		//	Used for binding
		//	a function to Lua
		//	6 Arguments
		//	Used internally
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
		class LuaFunction_6 : public LuaObject
		{
		public:
			typedef R(*Function)(P0, P1, P2, P3, P4, P5);
			typedef LuaFunction_6<R,P0,P1,P2,P3,P4,P5>	Type;

			LuaFunction_6(Lua* lpLua, Function lpFunction) : LuaObject(lpLua) , m_lpFunction(lpFunction) {}
			~LuaFunction_6() {}

			/*
			//	Used to actually bind
			//	the Function to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Function lpFunction);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Function
			*/
			int	call() const;

		private:
			Function	m_lpFunction;
		};



		/*
		//	Used for binding
		//	a function to Lua
		//	7 Arguments
		//	Used internally
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
		class LuaFunction_7 : public LuaObject
		{
		public:
			typedef R(*Function)(P0, P1, P2, P3, P4, P5, P6);
			typedef LuaFunction_7<R,P0,P1,P2,P3,P4,P5,P6>	Type;

			LuaFunction_7(Lua* lpLua, Function lpFunction) : LuaObject(lpLua) , m_lpFunction(lpFunction) {}
			~LuaFunction_7() {}

			/*
			//	Used to actually bind
			//	the Function to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Function lpFunction);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Function
			*/
			int	call() const;

		private:
			Function	m_lpFunction;
		};

	}

}

// Template Defenition
#include "LuaFunction.inl"

#endif